﻿namespace net.zxteam.ZXLexer.Dynamic
{
	using net.zxteam.ZXLexer.Dynamic.Internal;
	using net.zxteam.ZXLexer.Rules;
	using net.zxteam.ZXLexer.Tokens;
	using System;
	using System.Diagnostics.Contracts;

	public class DynamicLexer : ILexer
	{
		private readonly IAstRule _astRule;

		public DynamicLexer(IAstRule astRule)
		{
			Contract.Requires(astRule != null);

			if (astRule == null) throw new ArgumentNullException();

			_astRule = astRule;
		}

		public IAstToken Tokenize(ILexerSource source)
		{
			return new RuleVisitor(source).VisitAstRule(_astRule);
		}

		private class RuleVisitor : IRuleVisitor
		{
			private readonly ILexerSource _source;

			public RuleVisitor(ILexerSource source)
			{
				Contract.Requires(source != null);

				_source = source;
			}

			public IAstToken VisitAstRule(IAstRule astRule)
			{
				try
				{
					var innerToken = astRule.InnerRule.Accept(this);
					if (innerToken != null)
					{
						int startPosition = _source.Position;
						IAstToken token = new AstToken(innerToken);
						return token;
					}
				}
				catch (Exception ex)
				{
#warning
				}

				return null;
			}

			public ICardinalToken VisitCardinalRule(ICardinalRule cardinalRule)
			{
				throw new NotImplementedException();
			}

			public ICharRangeToken VisitCharRangeRule(ICharRangeRule charRangeToken)
			{
				throw new NotImplementedException();
			}

			public ICharToken VisitCharRule(ICharRule ruleChar)
			{
				throw new NotImplementedException();
			}

			public IChoiceToken VisitChoiceRule(IChoiceRule choiceRule)
			{

			}

			public IIndentToken VisitIndentRule(IIndentRule indentRule)
			{
				throw new NotImplementedException();
			}

			public ISequenceToken VisitSequenceRule(ISequenceRule sequenceToken)
			{
				throw new NotImplementedException();
			}

			public IStringToken VisitStringRule(IStringRule stringToken)
			{
				throw new NotImplementedException();
			}
		}
	}
}
